package com.iyoyi.skinlib;

import android.app.Activity;
import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

public class SkinManager {
    private static Application sApp;
    private static Resources sBaseRes;
    private static SkinResources sSkinRes;
    private static Resources sWorkRes;
    private static String sSkinName;
    private static List<SkinLayoutFactory> sFactoryList = new ArrayList<>();

    private SkinManager() {/**/}

    public static void init(Application app, Resources base) {
        Log.e("App", base.getClass().getName() + ": " + base.toString());

        sApp = app;
        sBaseRes = base;
        sWorkRes = sBaseRes;

        app.registerActivityLifecycleCallbacks(mLifecycleCallbacks);
    }

    public static void load(String name) throws PackageManager.NameNotFoundException, FileNotFoundException {
        if (!TextUtils.equals(sSkinName, name)) {
            File archiveFile = new File(sApp.getExternalFilesDir(null), name);
            if (!archiveFile.exists())
                throw new FileNotFoundException("File [" + name + "] not found");

            PackageManager packageManager = sApp.getPackageManager();

            int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS | PackageManager.GET_RECEIVERS | PackageManager.GET_META_DATA;
            final String archiveFilePath = archiveFile.getAbsolutePath();

            PackageInfo packageInfo = packageManager.getPackageArchiveInfo(archiveFilePath, flags);
            if (packageInfo == null)
                throw new FileNotFoundException("Archive File [" + name + "] not found");
            packageInfo.applicationInfo.publicSourceDir = archiveFilePath;
            packageInfo.applicationInfo.sourceDir = archiveFilePath;
            packageInfo.applicationInfo.processName = packageInfo.applicationInfo.packageName;
            Resources skinRes = packageManager.getResourcesForApplication(packageInfo.applicationInfo);

            sSkinRes = new SkinResources(sBaseRes, skinRes);
            sSkinName = name;
        }

        sWorkRes = sSkinRes;
        update(sWorkRes);
    }

    public static void restore() {
        sWorkRes = sBaseRes;
        update(sWorkRes);
    }

    private static void update(Resources resources) {
        for (SkinLayoutFactory factory2 : sFactoryList) {
            factory2.update(resources);
        }
    }

    public static Resources getResources() {
        return sWorkRes;
    }

    private static final Application.ActivityLifecycleCallbacks mLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {

        @Override
        public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
            LayoutInflater inflater = activity.getLayoutInflater();
            LayoutInflater.Factory2 factory2 = inflater.getFactory2();
            if (!(factory2 instanceof SkinLayoutFactory)) {
                factory2 = new SkinLayoutFactory((AppCompatActivity) activity, factory2);
                sFactoryList.add((SkinLayoutFactory) factory2);
                SkinLayoutFactory.forceSetFactory2(inflater, factory2);
            }
        }

        @Override
        public void onActivityStarted(@NonNull Activity activity) {

        }

        @Override
        public void onActivityResumed(@NonNull Activity activity) {

        }

        @Override
        public void onActivityPaused(@NonNull Activity activity) {

        }

        @Override
        public void onActivityStopped(@NonNull Activity activity) {

        }

        @Override
        public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {

        }

        @Override
        public void onActivityDestroyed(@NonNull Activity activity) {
            SkinLayoutFactory factory2 = (SkinLayoutFactory) activity.getLayoutInflater().getFactory2();
            factory2.destroy();
            sFactoryList.remove(factory2);
        }
    };
}
